package com.aube.control;

import android.content.Context;

import com.android.volley.cache.ACache;
import com.huyn.baseframework.dynamicload.video.model.GoodsFavorListModel;
import com.huyn.baseframework.dynamicload.video.model.GoodsItem;
import com.huyn.baseframework.utils.StringUtils;
import com.huyn.baseframework.utils.Utils;

import org.json.JSONArray;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 写数据到磁盘
 * 从磁盘同步数据
 * 数据缓存
 * Created by huyaonan on 16/3/30.
 */
public class DataManager {

    private static final String OBJECT_INDEX = "INDEX_";
    private static final String OBJECT_GOODS = "GOODS_";
    private static final String OBJECT_OPTION = "OPTION_";
    private static final String OBJECT_SELECTED = "SELECTED_";
    private static final String OBJECT_QA_RESULT = "QA_RESULT_";
    private static final String OBJECT_VIDEO_PLAYCOUNT = "PLAYCOUNT_";

    private static final String KEY_ID = "ID";
    private static final String KEY_INDEX = "INDEX";
    private static final String KEY_OPTION = "OPTION";
    private static final String KEY_MSG= "MSG";

    private static final String OPTION_ID = "OPTION_ID";
    private static final String OPTION_COUNT = "OPTION_COUNT";

    private static final String KEY_VIDEO_ID = "VIDEO_ID";
    private static final String VIDEO_PLAYCOUNT = "PLAY_COUNT";

    private String videoId;
    private static DataManager mManager;
    private Context context;

    private DataManager(Context context) {
        this.context = context;
    }

    public static synchronized DataManager getInstance(Context context) {
        if(mManager == null)
            mManager = new DataManager(context.getApplicationContext());
        return mManager;
    }

    public void save(String videoId) {
        if(StringUtils.isBlank(this.videoId))
            return;
        if(!this.videoId.equalsIgnoreCase(videoId))
            return;
        //save qa/vote/vs by videoid
        storeSelectedIndexes(videoId);
        //save goods by videoid
        storeGoods(videoId);
        //save options
        storeOptionData(videoId);
        //save selected option id
        storeOptionId(videoId);
        //save qa result id
        storeQAResult(videoId);
        //save video play count
        storeVideoPlayCount(videoId);
        this.videoId = null;
        mSelectedIndexMap.clear();
        mCollectedGoods.clear();
        mOptionCountMap.clear();
        mVideoPlayCountMap.clear();
    }

    public void restore(String videoId) {
        this.videoId = videoId;
        //restore qa/vote/vs by videoid
        reloadSelectedIndexes(videoId);
        //restore goods by videoid
        reloadGoods(videoId);
        //restore options
        reloadOptionData(videoId);
        //restore selected option id
        reloadOptionId(videoId);
        //restore qa result
        reloadQAResult(videoId);
        //restore video play count
        reloadVideoPlayCount(videoId);
    }

    private void reloadSelectedIndexes(String videoId) {
        try {
            if(mSelectedIndexMap == null)
                mSelectedIndexMap = new HashMap<>();
            JSONArray jsonArray =  ACache.get(context).getAsJSONArray(OBJECT_INDEX + videoId);
            if(jsonArray == null)
                return;
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject item = jsonArray.optJSONObject(i);
                mSelectedIndexMap.put(item.optString(KEY_ID), item.optInt(KEY_INDEX));
            }
        } catch (Exception e) {
            e.printStackTrace();

            ACache.get(context).remove(OBJECT_INDEX + videoId);
        }
    }

    private void reloadGoods(String videoId) {
        try {
            if(mCollectedGoods == null)
                mCollectedGoods = new HashMap<>();
            ACache.CacheFeed feed =  ACache.get(context).getAsObject(OBJECT_GOODS + videoId);
            if(feed == null || feed.object == null)
                return;
            GoodsFavorListModel list = (GoodsFavorListModel) feed.object;
            for (int i = 0; i < list.getSize(); i++) {
                GoodsItem item = list.get(i);
                mCollectedGoods.put(item._id, item);
            }
        } catch (Exception e) {
            e.printStackTrace();

            ACache.get(context).remove(OBJECT_GOODS + videoId);
        }
    }

    private void reloadOptionId(String rid) {
        try {
            if(mSelectedOptionIds == null)
                mSelectedOptionIds = new HashMap<>();
            JSONArray jsonArray =  ACache.get(context).getAsJSONArray(OBJECT_SELECTED + rid);
            if(jsonArray == null)
                return;
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject item = jsonArray.optJSONObject(i);
                mSelectedOptionIds.put(item.optString(KEY_ID), item.optString(KEY_OPTION));
            }
        } catch (Exception e) {
            e.printStackTrace();

            ACache.get(context).remove(OBJECT_SELECTED + videoId);
        }
    }

    private void reloadQAResult(String rid) {
        try {
            if(mQAResultMap == null)
                mQAResultMap = new HashMap<>();
            JSONArray jsonArray =  ACache.get(context).getAsJSONArray(OBJECT_QA_RESULT + rid);
            if(jsonArray == null)
                return;
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject item = jsonArray.optJSONObject(i);
                mQAResultMap.put(item.optString(KEY_ID), item.optString(KEY_MSG));
            }
        } catch (Exception e) {
            e.printStackTrace();

            ACache.get(context).remove(OBJECT_QA_RESULT + videoId);
        }
    }

    private void storeQAResult(String rid) {
        try {
            if(mQAResultMap == null)
                return;
            Iterator<Map.Entry<String, String>> iterator = mQAResultMap.entrySet().iterator();
            JSONArray array = new JSONArray();
            while (iterator.hasNext()) {
                Map.Entry<String, String> entry = iterator.next();
                JSONObject object = new JSONObject();
                object.put(KEY_ID, entry.getKey());
                object.put(KEY_MSG, entry.getValue());
                array.put(object);
            }
            ACache.get(context).put(OBJECT_QA_RESULT + rid, array);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void storeOptionId(String rid) {
        try {
            if(mSelectedOptionIds == null)
                return;
            Iterator<Map.Entry<String, String>> iterator = mSelectedOptionIds.entrySet().iterator();
            JSONArray array = new JSONArray();
            while (iterator.hasNext()) {
                Map.Entry<String, String> entry = iterator.next();
                JSONObject object = new JSONObject();
                object.put(KEY_ID, entry.getKey());
                object.put(KEY_OPTION, entry.getValue());
                array.put(object);
            }
            ACache.get(context).put(OBJECT_SELECTED + rid, array);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void storeSelectedIndexes(String videoId) {
        try {
            if(mSelectedIndexMap == null)
                return;
            Iterator<Map.Entry<String, Integer>> iterator = mSelectedIndexMap.entrySet().iterator();
            JSONArray array = new JSONArray();
            while (iterator.hasNext()) {
                Map.Entry<String, Integer> entry = iterator.next();
                JSONObject object = new JSONObject();
                object.put(KEY_ID, entry.getKey());
                object.put(KEY_INDEX, entry.getValue());
                array.put(object);
            }
            ACache.get(context).put(OBJECT_INDEX + videoId, array);
        } catch (Exception e) {

        }
    }

    private void storeGoods(String videoId) {
        try {
            if(mCollectedGoods == null)
                return;
            Iterator<Map.Entry<String, GoodsItem>> iterator = mCollectedGoods.entrySet().iterator();
            GoodsFavorListModel list = new GoodsFavorListModel();
            while (iterator.hasNext()) {
                Map.Entry<String, GoodsItem> entry = iterator.next();
                list.add(entry.getValue());
            }
            ACache.get(context).put(OBJECT_GOODS + videoId, list);
        } catch (Exception e) {

        }
    }

    /**
     * 存储vote/pk/qa的选中索引
     */
    private HashMap<String, Integer> mSelectedIndexMap = new HashMap<>();

    private HashMap<String, GoodsItem> mCollectedGoods = new HashMap<>();

    /**
     * 存储vote/pk/qa选中的id
     */
    private HashMap<String, String> mSelectedOptionIds = new HashMap<>();

    /**
     * 存储pk和vote的每一项的数量
     */
    private static HashMap<String, Integer> mOptionCountMap = new HashMap<>();

    /**
     * qa中奖结果
     */
    private static HashMap<String, String> mQAResultMap = new HashMap<>();

    /**
     * 存储视频播放次数
     * @param rid
     * @param msg
     */
    private static HashMap<String, Integer> mVideoPlayCountMap = new HashMap<>();

    public void updateQAResult(String rid, String msg) {
        if(mQAResultMap == null)
            mQAResultMap = new HashMap<>();
        mQAResultMap.put(rid, msg);
    }

    public String getQAResult(String rid) {
        if(mQAResultMap == null)
            return "";
        return mQAResultMap.get(rid);
    }

    public void updateSelectedOptionId(String rid, String optionId) {
        if(mSelectedOptionIds == null)
            mSelectedOptionIds = new HashMap<>();
        if(StringUtils.isNotBlank(optionId)) {
            mSelectedOptionIds.put(rid, optionId);
        } else {
            if(mSelectedOptionIds.containsKey(rid))
                mSelectedOptionIds.remove(rid);
        }
    }

    public String getSelectedOptionId(String rid) {
        if(mSelectedOptionIds == null)
            return null;
        return mSelectedOptionIds.get(rid);
    }

    public void clear() {
        try {
            mSelectedIndexMap.clear();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void update(String key , int value) {
        if(mSelectedIndexMap == null)
            mSelectedIndexMap = new HashMap<>();
        if(mSelectedIndexMap.containsKey(key)) {
            mSelectedIndexMap.remove(key);
        }
        if(value >=0)
            mSelectedIndexMap.put(key, value);
    }

    public int getIndex(String key) {
        if(mSelectedIndexMap == null) {
            mSelectedIndexMap = new HashMap<>();
            return -1;
        }
        if(mSelectedIndexMap.containsKey(key))
            return mSelectedIndexMap.get(key);
        return -1;
    }

    public boolean update(List<GoodsItem> data) {
        if(data == null || data.size() == 0)
            return false;
        for(GoodsItem item : data)
            update(item._id, item);
        return true;
    }

    public void update(String key, GoodsItem goodsItem) {
        if(mCollectedGoods == null)
            mCollectedGoods = new HashMap<>();
        if(mCollectedGoods.containsKey(key)) {
            mCollectedGoods.remove(key);
        }
        mCollectedGoods.put(key, goodsItem);
    }

    public void delete(String key) {
        if(mCollectedGoods == null)
            mCollectedGoods = new HashMap<>();
        if(mCollectedGoods.containsKey(key)) {
            mCollectedGoods.remove(key);
        }
    }

    public boolean hasCollected(String id) {
        if(mCollectedGoods == null)
            return false;
        return mCollectedGoods.containsKey(id);
    }

    public Iterator<Map.Entry<String, GoodsItem>> goodsIterator() {
        if(mCollectedGoods == null)
            mCollectedGoods = new HashMap<>();
        return mCollectedGoods.entrySet().iterator();
    }

    public int getOptionCount(String rid) {
        if(mOptionCountMap == null || !mOptionCountMap.containsKey(rid))
            return 0;
        return mOptionCountMap.get(rid);
    }

    public void updateOptionCount(String id, int count) {
        if(mOptionCountMap == null)
            mOptionCountMap = new HashMap<>();
        if(StringUtils.isBlank(id))
            return;
        mOptionCountMap.put(id, count >= 0 ? count : 0);
    }

    public void updateOptionCount(String id, boolean minus) {
        if(mOptionCountMap == null)
            mOptionCountMap = new HashMap<>();
        if(StringUtils.isBlank(id))
            return;
        if(mOptionCountMap.containsKey(id)) {
            int count = mOptionCountMap.get(id);
            if(minus)
                mOptionCountMap.put(id, count > 0 ? (count-1) : 0);
            else
                mOptionCountMap.put(id, count >= 0 ? count+1 : 1);
        } else {
            mOptionCountMap.put(id, minus ? 0 : 1);
        }
    }

    public void updateOptionCount(String id, int count, boolean minus) {
        if(mOptionCountMap == null)
            mOptionCountMap = new HashMap<>();
        if(StringUtils.isBlank(id))
            return;
        if(minus)
            mOptionCountMap.put(id, count > 0 ? (count-1) : 0);
        else
            mOptionCountMap.put(id, count >= 0 ? count+1 : 1);
    }

    private void reloadOptionData(String videoId) {
        try {
            if(mOptionCountMap == null)
                mOptionCountMap = new HashMap<>();
            JSONArray jsonArray =  ACache.get(context).getAsJSONArray(OBJECT_OPTION + videoId);
            if(jsonArray == null)
                return;
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject item = jsonArray.optJSONObject(i);
                mOptionCountMap.put(item.optString(OPTION_ID), item.optInt(OPTION_COUNT));
            }
        } catch (Exception e) {
            e.printStackTrace();

            ACache.get(context).remove(OBJECT_OPTION + videoId);
        }
    }

    private void storeOptionData(String videoId) {
        try {
            if(mOptionCountMap == null)
                return;
            Iterator<Map.Entry<String, Integer>> iterator = mOptionCountMap.entrySet().iterator();
            JSONArray array = new JSONArray();
            while (iterator.hasNext()) {
                Map.Entry<String, Integer> entry = iterator.next();
                JSONObject object = new JSONObject();
                object.put(OPTION_ID, entry.getKey());
                object.put(OPTION_COUNT, entry.getValue());
                array.put(object);
            }
            ACache.get(context).put(OBJECT_OPTION + videoId, array);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public int getVideoPlayCount(String rid) {
        if(mVideoPlayCountMap == null || !mVideoPlayCountMap.containsKey(rid))
            return 0;
        return mVideoPlayCountMap.get(rid);
    }

    public void updateVideoPlayCount(String id, boolean minus) {
        if(mVideoPlayCountMap == null)
            mVideoPlayCountMap = new HashMap<>();
        if(StringUtils.isBlank(id))
            return;
        if(mVideoPlayCountMap.containsKey(id)) {
            int count = mVideoPlayCountMap.get(id);
            if(minus)
                mVideoPlayCountMap.put(id, count > 0 ? (count-1) : 0);
            else
                mVideoPlayCountMap.put(id, count >= 0 ? count+1 : 1);
        } else {
            mVideoPlayCountMap.put(id, minus ? 0 : 1);
        }
    }

    private void reloadVideoPlayCount(String videoId) {
        try {
            if(mVideoPlayCountMap == null)
                mVideoPlayCountMap = new HashMap<>();
            JSONArray jsonArray =  ACache.get(context).getAsJSONArray(OBJECT_VIDEO_PLAYCOUNT + videoId);
            if(jsonArray == null)
                return;
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject item = jsonArray.optJSONObject(i);
                mVideoPlayCountMap.put(item.optString(KEY_VIDEO_ID), item.optInt(VIDEO_PLAYCOUNT));
            }
        } catch (Exception e) {
            e.printStackTrace();

            ACache.get(context).remove(OBJECT_VIDEO_PLAYCOUNT + videoId);
        }
    }

    private void storeVideoPlayCount(String videoId) {
        try {
            if(mVideoPlayCountMap == null)
                return;
            Iterator<Map.Entry<String, Integer>> iterator = mVideoPlayCountMap.entrySet().iterator();
            JSONArray array = new JSONArray();
            while (iterator.hasNext()) {
                Map.Entry<String, Integer> entry = iterator.next();
                JSONObject object = new JSONObject();
                object.put(KEY_VIDEO_ID, entry.getKey());
                object.put(VIDEO_PLAYCOUNT, entry.getValue());
                array.put(object);
            }
            ACache.get(context).put(OBJECT_VIDEO_PLAYCOUNT + videoId, array);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
